<script setup lang="ts">
  import { useGetOrderEndFieldList, useSaveOrderEndResult } from '@/services/pages/order/useOrder'
  import { FormInstance, UploadFile, UploadRawFile } from 'element-plus'
  import { computed, PropType, ref, watch } from 'vue'
  import VideoPreview from '@/components/pages/return-factory/index/create/custom-info/VideoPreview.vue'
  import PdfPreview from '@/components/pages/return-factory/index/create/custom-info/PdfPreview.vue'
  import videoCover from '@/assets/image/pages/order/new/video.png'
  import fileIcon from '@/assets/image/modules/code/detail-work-drawing.svg'
  import { HMessage, HMessageBox } from '@/components/common/message'
  import { fileUpload } from '@/api/upload'
  import { useGetModuleOptions } from '@/services/pages/order/useModule'
  import { useGetTemplateByModuleAndOrderId } from '@/services/pages/order/useOrderDetail'
  import { UploadFilled } from '@element-plus/icons-vue'

  const {
    fieldList,
    getListLoading,
    getList: getFieldList,
    resetFieldList,
  } = useGetOrderEndFieldList()
  const { saveForm, saveLoading, resetForm, save } = useSaveOrderEndResult()
  const {
    options: moduleOptions,
    getOptionsParam: getModuleOptionsParam,
    getOptionsLoading: getModuleOptionsLoading,
    getOptions: getModuleOptions,
  } = useGetModuleOptions()
  const { template, getTemplateParam, getTemplateLoading, getTemplate } =
    useGetTemplateByModuleAndOrderId()

  defineOptions({ name: 'EndOrderFormModal' })

  interface FileListItem {
    file: UploadRawFile
    url: string
  }

  const props = defineProps({
    endStatus: {
      type: Boolean,
      required: true,
    },
    orderDetail: {
      type: Object as PropType<OrderDetail>,
      required: true,
    },
    goodList: {
      type: Array as PropType<Array<OrderDetailAPIResponse.GoodListItem>>,
      required: true,
    },
  })

  const emits = defineEmits<{
    (e: 'update'): void
    (
      e: 'order-data-check-before-submit',
      value: { faultTypeVoid: boolean; goodNoSnCode: boolean },
    ): void
  }>()

  const fileUploadLoading = ref(false)
  const previewVideoList = ref<Array<string>>([])
  const templateFormInstance = ref<Array<FormInstance> | null>(null)
  const previewVideoIndex = ref(-1)
  const videoPreviewModalVisible = ref(false)
  const previewPdfList = ref<Array<string>>([])
  const previewPdfIndex = ref(-1)
  const pdfPreviewModalVisible = ref(false)
  const visible = defineModel('modelValue', { type: Boolean, default: false })
  const activeModule = computed(() => {
    return moduleOptions.value.find((item) => item.id === getTemplateParam.value.moduleId)
  })
  const loading = computed(() => {
    return (
      getListLoading.value ||
      saveLoading.value ||
      fileUploadLoading.value ||
      getModuleOptionsLoading.value ||
      getTemplateLoading.value
    )
  })

  const handleUploadFile = (
    file: UploadFile,
    templateIndex: number,
    fieldId: string,
    type: 'picture' | 'video' | 'pdf',
  ) => {
    const template = fieldList.value[templateIndex]
    if (!template || !file.raw) return

    const fieldIndex = template.content.findIndex((item) => item.propertyId === fieldId)
    if (fieldIndex === -1) return

    const field = template.content[fieldIndex]
    let newField: (typeof field & { fileList: Array<FileListItem> }) | null = null
    if ('fileList' in field) {
      newField = field as typeof field & { fileList: Array<FileListItem> }
    } else {
      newField = Object.assign(field, {
        fileList: [],
      })
    }

    if (type === 'picture') {
      if (!file.raw.type.includes('image')) {
        HMessageBox.error('只能上传图片')
        return
      }
    }

    if (type === 'pdf') {
      if (!file.raw.type.includes('pdf')) {
        HMessageBox.error('只能上传pdf')
        return
      }
    }

    if (type === 'video') {
      if (!file.raw.type.includes('video')) {
        HMessageBox.error('只能上传视频')
        return
      }
    }

    if (file.raw.size / 1024 / 1024 > field.uploadSize) {
      HMessageBox.error(`文件大小不能超过${field.uploadSize}MB!`)
      return
    }

    if (newField.fileList.length >= field.uploadQty) {
      HMessageBox.error(`最多上传${field.uploadQty}${type === 'picture' ? '张' : '个'}`)
      return
    }

    newField.fileList.push({ file: file.raw, url: URL.createObjectURL(file.raw) })
    fieldList.value[templateIndex].content[fieldIndex] = newField
  }

  const hideDrawer = () => {
    resetFieldList()
    resetForm()
    visible.value = false
  }

  const onSave = async (type: 0 | 1 | 2 | 3) => {
    try {
      if (type !== 2) {
        if (!templateFormInstance.value || templateFormInstance.value.length <= 0) {
          return false
        }

        for (let i = 0; i < templateFormInstance.value.length; i++) {
          await templateFormInstance.value[i].validate()
        }
      }

      for (let i = 0; i < fieldList.value.length; i++) {
        const template = fieldList.value[i]
        for (let fieldIndex = 0; fieldIndex < template.content.length; fieldIndex++) {
          const field = template.content[fieldIndex]

          /**
           * 文件上传
           * 如果有选择图片就将图片放到服务器上，再将请求后的路径放到fileList里
           * 并过滤已经上传了文件的对象
           */
          if ([5, 6, 7].includes(field.type) && field.fileList) {
            const fileList = field.fileList.map((item) => item.file)
            if (fileList.length > 0) {
              fileUploadLoading.value = true
              const res = await fileUpload(fileList)
              fileUploadLoading.value = false
              res.data.data.rows.forEach((item) => {
                if (field.fileList) {
                  field.fileList.push({
                    file: null,
                    url: item,
                  })
                }
              })
              field.fileList = field.fileList.filter((item) => !item.file)
            }
            fieldList.value[i].content[fieldIndex].value = JSON.stringify(
              field.fileList.map((item) => item.url),
            )
          }

          if (field.type === 4) {
            fieldList.value[i].content[fieldIndex].value = JSON.stringify(
              field.value as unknown as Array<string>,
            )
          }
        }
      }

      saveForm.value = fieldList.value
      const moduleId = props.endStatus
        ? props.orderDetail.moduleId
        : getTemplateParam.value.moduleId
      const res = await save(props.orderDetail.id, type, moduleId)
      if (res.code === 20000) {
        HMessage.success('保存成功')
        emits('update')
        hideDrawer()
        return
      }
      HMessageBox.error(res.message)
    } catch (error) {
      // error
    }
  }

  const translateSelectOption = (choices: string) => {
    try {
      const result: Array<{ label: string; value: string }> = []
      if (JSON.parse(choices).map) {
        JSON.parse(choices).forEach((item) => {
          if (item.val && item.id) {
            result.push({
              label: item.val,
              value: String(item.id),
            })
          }
        })
      }
      return result
    } catch (error) {
      return []
    }
  }

  const handleFileDel = (templateIndex: number, fieldId: string, fileIndex: number) => {
    const template = fieldList.value[templateIndex]
    if (!template) {
      return
    }

    const fieldIndex = template.content.findIndex((item) => item.propertyId === fieldId)
    if (fieldIndex === -1) {
      return
    }

    if (fieldList.value[templateIndex].content[fieldIndex].fileList) {
      fieldList.value[templateIndex].content[fieldIndex].fileList.splice(fileIndex, 1)
    }
  }

  const handleVideoPreview = (templateIndex: number, fieldId: string, fileIndex: number) => {
    const template = fieldList.value[templateIndex]
    if (!template) {
      return
    }

    const fieldIndex = template.content.findIndex((item) => item.propertyId === fieldId)
    if (fieldIndex === -1) {
      return
    }

    if (template.content[fieldIndex].fileList) {
      previewVideoList.value = template.content[fieldIndex].fileList.map((file) => file.url)
      previewVideoIndex.value = fileIndex
      videoPreviewModalVisible.value = true
    }
  }

  const handlePdfPreview = (templateIndex: number, fieldId: string, fileIndex: number) => {
    const template = fieldList.value[templateIndex]
    if (!template) {
      return
    }

    const fieldIndex = template.content.findIndex((item) => item.propertyId === fieldId)
    if (fieldIndex === -1) {
      return
    }

    if (template.content[fieldIndex].fileList) {
      previewPdfList.value = template.content[fieldIndex].fileList.map((file) => file.url)
      previewPdfIndex.value = fileIndex
      pdfPreviewModalVisible.value = true
    }
  }

  const handleOrderModuleSelect = async () => {
    await getTemplate()
    fieldList.value = template.value.objects
  }

  const init = async () => {
    getModuleOptionsParam.value.departmentId = props.orderDetail.departmentId
    await getModuleOptions()

    getTemplateParam.value.moduleId = props.orderDetail.moduleId
    getTemplateParam.value.orderId = props.orderDetail.id
    await getFieldList(props.orderDetail.id)
    for (let templateIndex = 0; templateIndex < fieldList.value.length; templateIndex++) {
      const template = fieldList.value[templateIndex]
      for (let fieldIndex = 0; fieldIndex < template.content.length; fieldIndex++) {
        const field = template.content[fieldIndex]
        if ([5, 6, 7].includes(field.type) && field.value) {
          field.fileList = JSON.parse(field.value).map((item) => {
            return {
              file: null,
              url: item,
            }
          })
        }

        if (field.type === 4 && field.value) {
          field.value = JSON.parse(field.value)
        }
      }
    }
    if (!activeModule.value) {
      HMessageBox.error('当前模块已被禁用，请切换')
    }
  }

  watch(visible, (value) => {
    value && init()
  })
</script>

<template>
  <h-drawer
    v-model="visible"
    :title="props.endStatus ? '修改结单信息' : '申请结单'"
    :loading="loading"
    :width="1000"
    unit="px"
    @close="hideDrawer"
  >
    <div v-if="!props.endStatus" class="order-module-select">
      <div class="label">工单类型</div>
      <el-select
        v-model="getTemplateParam.moduleId"
        placeholder="请选择工单类型"
        style="width: 240px"
        @change="handleOrderModuleSelect"
      >
        <el-option
          v-for="(moduleOption, moduleOptionIndex) in moduleOptions"
          :key="moduleOptionIndex"
          :label="moduleOption.name"
          :disabled="moduleOption.disabled"
          :value="moduleOption.id"
        />
      </el-select>
    </div>
    <div class="form-container">
      <el-form
        v-for="(template, templateIndex) in fieldList"
        ref="templateFormInstance"
        :key="templateIndex"
        :model="template"
        inline-message
        label-position="top"
      >
        <div class="form">
          <div class="title">{{ template.templateName }}</div>
          <div class="line"></div>
          <div class="field-list">
            <template
              v-for="(field, fieldIndex) in template.content.filter(
                (templateField) => !templateField.disabled,
              )"
              :key="fieldIndex"
            >
              <el-form-item
                :label="field.property"
                :rules="[
                  {
                    validator: (rule, value, callback) => {
                      if (field.required && [5, 6, 7].includes(field.type)) {
                        if (!field.fileList || field.fileList.length <= 0) {
                          return new Error(field.tip || `${field.property}不能为空`)
                        }
                        callback()
                        return
                      }

                      if (
                        field.required &&
                        (field.value === '' || field.value === null || field.value === undefined)
                      ) {
                        return new Error(field.tip || `${field.property}不能为空`)
                      }

                      callback()
                    },
                    trigger: ['change', 'blur'],
                  },
                ]"
                prop="value"
              >
                <template #label>
                  <div>
                    <span v-if="field.required" style="color: #f56c6c">*</span>
                    {{ field.property }}
                  </div>
                </template>

                <el-input
                  v-if="field.type === 1"
                  v-model="field.value"
                  :placeholder="field.tip || `请输入${field.property}`"
                />

                <el-input
                  v-if="field.type === 2"
                  v-model="field.value"
                  :placeholder="field.tip || `请输入${field.property}`"
                  type="textarea"
                  show-word-limit
                  maxlength="200"
                />

                <el-select
                  v-if="field.type === 3 && field.choices"
                  v-model="field.value"
                  :placeholder="field.tip || `请选择${field.property}`"
                >
                  <el-option
                    v-for="(option, optionIndex) in translateSelectOption(field.choices)"
                    :key="optionIndex"
                    :label="option.label"
                    :value="option.value"
                  />
                </el-select>

                <el-select
                  v-if="field.type === 4 && field.choices"
                  v-model="field.value"
                  :placeholder="field.tip || `请选择${field.property}`"
                  multiple
                >
                  <el-option
                    v-for="(option, optionIndex) in translateSelectOption(field.choices)"
                    :key="optionIndex"
                    :label="option.label"
                    :value="option.value"
                  />
                </el-select>

                <el-rate v-if="field.type === 8" v-model="field.value" />

                <el-date-picker
                  v-if="field.type === 9"
                  v-model="field.value"
                  type="date"
                  :placeholder="field.tip || `请选择${field.property}`"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"
                />

                <el-date-picker
                  v-if="field.type === 10"
                  v-model="field.value"
                  type="datetime"
                  :placeholder="field.tip || `请选择${field.property}`"
                  format="YYYY-MM-DD hh:mm:ss"
                  value-format="YYYY-MM-DD hh:mm:ss"
                />

                <div v-if="field.type === 5" class="file-list">
                  <el-upload
                    :auto-upload="false"
                    :show-file-list="false"
                    accept="image/*"
                    action="#"
                    drag
                    multiple
                    :on-change="(file: UploadFile) => handleUploadFile(file, templateIndex, field.propertyId, 'picture')"
                  >
                    <el-icon :size="24" color="#007cff">
                      <UploadFilled />
                    </el-icon>
                  </el-upload>
                  <h-image
                    v-for="(file, fileIndex) in field.fileList"
                    :key="fileIndex"
                    :width="80"
                    :height="50"
                    :src="file.url"
                    :preview-src-list="field.fileList.map((item) => item.url)"
                    :padding="2"
                    @del="handleFileDel(templateIndex, field.propertyId, fileIndex)"
                  />
                </div>

                <div v-if="field.type === 6" class="file-list">
                  <el-upload
                    :auto-upload="false"
                    :show-file-list="false"
                    accept=".pdf"
                    action="#"
                    drag
                    multiple
                    :on-change="(file: UploadFile) => handleUploadFile(file, templateIndex, field.propertyId, 'pdf')"
                  >
                    <el-icon :size="24" color="#007cff">
                      <UploadFilled />
                    </el-icon>
                  </el-upload>
                  <h-image
                    v-for="(file, fileIndex) in field.fileList"
                    :key="fileIndex"
                    :width="80"
                    :height="50"
                    :padding="2"
                    :src="fileIcon"
                    :is-show-img-preview="false"
                    @del="handleFileDel(templateIndex, field.propertyId, fileIndex)"
                    @preview="handlePdfPreview(templateIndex, field.propertyId, fileIndex)"
                  />
                </div>

                <div v-if="field.type === 7" class="file-list">
                  <el-upload
                    :auto-upload="false"
                    :show-file-list="false"
                    accept="video/*"
                    action="#"
                    drag
                    multiple
                    :on-change="(file: UploadFile) => handleUploadFile(file, templateIndex, field.propertyId, 'video')"
                  >
                    <el-icon :size="24" color="#007cff">
                      <UploadFilled />
                    </el-icon>
                  </el-upload>
                  <h-image
                    v-for="(file, fileIndex) in field.fileList"
                    :key="fileIndex"
                    :width="80"
                    :height="50"
                    :padding="2"
                    :src="videoCover"
                    :is-show-img-preview="false"
                    @del="handleFileDel(templateIndex, field.propertyId, fileIndex)"
                    @preview="handleVideoPreview(templateIndex, field.propertyId, fileIndex)"
                  />
                </div>
              </el-form-item>
            </template>
          </div>
        </div>
      </el-form>
    </div>

    <template #footer>
      <h-button v-permission="'order_end_submit'" is-modal type="primary" @click="onSave(0)">
        提交
      </h-button>
      <template v-if="props.endStatus">
        <h-button v-permission="'order_end_pass'" is-modal type="primary" @click="onSave(1)">
          审核通过
        </h-button>
        <h-button v-permission="'order_end_reject'" is-modal type="error" @click="onSave(2)">
          审核驳回
        </h-button>
      </template>
      <h-button
        v-else
        v-permission="'order_end_submit_check'"
        is-modal
        type="primary"
        @click="onSave(3)"
      >
        提交并审核
      </h-button>
      <h-button is-modal @click="hideDrawer">取消</h-button>
    </template>

    <video-preview
      v-model:visible="videoPreviewModalVisible"
      :initial-index="previewVideoIndex"
      :video-list="previewVideoList"
    />

    <pdf-preview
      v-model:visible="pdfPreviewModalVisible"
      :initial-index="previewPdfIndex"
      :pdf-list="previewPdfList"
    />
  </h-drawer>
</template>

<style scoped lang="scss">
  :deep(.el-form-item__error) {
    margin: 0;
  }

  .order-module-select {
    display: flex;
    align-items: center;
    column-gap: 12px;
    margin-bottom: 12px;

    .label {
      font-weight: bold;
    }
  }

  .form-container {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    column-gap: 24px;

    .form {
      .title {
        font-size: 14px;
        font-weight: bold;
        border-left: 2px solid #007cff;
        padding-left: 6px;
        margin-bottom: 4px;
      }

      .line {
        border-bottom: 1px solid rgb(240, 240, 240);
      }

      .field-list {
        display: flex;
        flex-direction: column;
        row-gap: 12px;

        .third-info-img-list {
          display: flex;
          column-gap: 12px;
        }

        :deep(.el-form-item) {
          .el-form-item__label {
            margin: 0;
            padding: 0;
          }

          .el-form-item__content {
            .el-select {
              .el-select__wrapper {
                height: auto;
              }
            }

            .el-textarea {
              .el-textarea__inner {
                height: 100px;
              }
            }

            .el-upload {
              width: 80px;
              height: 50px;

              .el-upload-dragger {
                display: flex;
                align-items: center;
                column-gap: 5px;
                width: 100%;
                height: 100%;
                padding: 0;
                background: none;
                justify-content: center;
              }
            }

            .file-list {
              display: flex;
              flex-wrap: wrap;
              gap: 12px;
            }
          }
        }
      }
    }
  }
</style>
